﻿#region Disclaimer / License
// Copyright (C) 2011, Kenneth Bergeron, IAP Worldwide Services, Inc
// NOAA :: National Marine Fisheries Service
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
// 
#endregion
using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace CatchProcessing
{
    using LocalDataSet = DataSets.LocalDataSet;
    /// <summary>
    /// Main form
    /// </summary>
    public partial class CatchProcessing : Form
    {
        /// <summary>
        /// The Local XML data set
        /// </summary>
        private LocalDataSet LocalData { get; set; }
        /// <summary>
        /// Shorthand for the property
        /// </summary>
        private string VesselCode { get { return Properties.Settings.Default.VesselCode; } }
        /// <summary>
        /// Shorthand for the Cruise
        /// </summary>
        private string Cruise { get { return Properties.Settings.Default.Cruise; } }
        /// <summary>
        /// The current station
        /// </summary>
        private string Station
        {
            get { return Properties.Settings.Default.Station; }
            set { Properties.Settings.Default.Station = value; Properties.Settings.Default.Save(); }
        }
        /// <summary>
        /// Main form
        /// </summary>
        public CatchProcessing()
        {
            InitializeComponent();
            this.onScreenKeyboardToolStripMenuItem.Click += new EventHandler(OnScreenKeyboard.OnScreenKeyboardToolStripMenuItem_Click);
            // Load the local XML
            this.LocalData = new LocalDataSet();
            this.LocalData.Load();
            // Set the bindings
            this.fishBindingSource.DataSource = this.LocalData;
            this.fishBindingSource.DataMember = "Fish";
            bool Sane = Sanity();
            // Setup the station selector
            this.StationComboBox.Items.Clear();
            this.StationComboBox.Items.AddRange( DataSets.Glob.theEASADataSet.StationCodes(VesselCode, Cruise) );
            if (this.StationComboBox.Items.Count > 0)
            {
                int ix = this.StationComboBox.FindStringExact(Station);
                if (ix >= 0)
                    this.StationComboBox.SelectedIndex = ix;
            }
            // This starts a background worker that loads the Taxonomy database
            Taxonomy.LoadTax();
            // Fill the table
            if(Sane) Setup();
        }
        /// <summary>
        /// Loaded, restore the window size
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            // If there is a saved window size and the screen info has not changed, resize the window
            if (Properties.Settings.Default.IsMainWindowStateDefined && SystemInformation.VirtualScreen.Size == Properties.Settings.Default.MainWorkingArea)
            {
                this.WindowState = Properties.Settings.Default.MainFormWindowState;
                if (this.WindowState != FormWindowState.Maximized)
                {
                    this.Size = Properties.Settings.Default.MainWindowSize;
                    this.Location = Properties.Settings.Default.MainWindowPosition;
                }
            }
        }
        /// <summary>
        /// All done, save the window size, location, state
        /// </summary>
        protected override void OnClosing(CancelEventArgs e)
        {
            SaveForm();
            base.OnClosing(e);
        }
        /// <summary>
        /// Save the size, location, state
        /// </summary>
        private void SaveForm()
        {
            Properties.Settings.Default.MainWorkingArea = SystemInformation.VirtualScreen.Size;
            Properties.Settings.Default.MainWindowSize = this.Size;
            Properties.Settings.Default.MainFormWindowState = this.WindowState;
            Properties.Settings.Default.MainWindowPosition = this.Location;
            Properties.Settings.Default.Save();
        }
        /// <summary>
        /// Check the settings
        /// </summary>
        /// <returns>true if OK</returns>
        private bool Sanity()
        {
            // No vessel?  Make them enter one first
            if ((string.IsNullOrEmpty(Properties.Settings.Default.VesselCode) ||
                string.IsNullOrEmpty(this.Cruise)) &&
                this.LocalData.Fish.Count == 0)
            {
                MessageBox.Show("Use File->Setup to set Vessel and Cruise.");
                return false;
            }
            // Sanity check
            if (string.IsNullOrEmpty(Properties.Settings.Default.VesselCode))
            {
                Properties.Settings.Default.VesselCode = this.LocalData.Fish[0].VesselCode;
                Properties.Settings.Default.Save();
            }
            if (string.IsNullOrEmpty(Properties.Settings.Default.Cruise))
            {
                Properties.Settings.Default.Cruise = this.LocalData.Fish[0].Cruise;
                Properties.Settings.Default.Save();
            }
            if (string.IsNullOrEmpty(Properties.Settings.Default.Station))
            {
                Properties.Settings.Default.Station = this.LocalData.Fish[0].Station;
                Properties.Settings.Default.Save();
            }
            return true;
        }
        /// <summary>
        /// Fill the table
        /// </summary>
        private void Setup()
        {
            SetHeader();
            // Set the binding filter to only see records from this vessel, cruise and station
            try
            {
                this.fishBindingSource.Filter = "VesselCode = '" + this.VesselCode + "' AND Cruise = '" + 
                    this.Cruise + "' AND Station = '" + this.Station + "'";
            }
            catch
            {
                this.fishBindingSource.Filter = "FALSE";
            }
            this.fishBindingSource.DataSource = this.LocalData;
            this.fishBindingSource.DataMember = "Fish";
        }
        /// <summary>
        /// Sets the window title and bar
        /// </summary>
        private void SetHeader()
        {
            this.CruiseTextBox.Text = this.Cruise;
            this.Text = "Catch Processing " + DataSets.Glob.Support.VesselName(this.VesselCode);
        }
        /// <summary>
        /// Pressed ADD Station, add a statioin and a record
        /// </summary>
        private void AddStationToolStripButton_Click(object sender, EventArgs e)
        {
            // Find the last used station number
            var Query = from LocalDataSet.FishRow qRow in this.LocalData.Fish
                        where qRow.Cruise == this.Cruise && qRow.VesselCode == this.VesselCode
                        orderby qRow.Station
                        select qRow.Station;
            string LastStation = Query.DefaultIfEmpty(string.Empty).Last();
            int sn = 0;
            int.TryParse(LastStation, out sn);
            sn++;
            // Get the new station number
            NewStationDialog nsd = new NewStationDialog();
            nsd.Station = sn.ToString("000");
            // Keep asking util Cancel or a new station is entered
            while(nsd.ShowDialog() == DialogResult.OK && Query.Where(qR=>qR.Equals(nsd.Station)).Any())
                MessageBox.Show("Station number " + nsd.Station + " is in use.  Select another or [Cancel].");
            if (nsd.DialogResult == System.Windows.Forms.DialogResult.Cancel) return;
            // Set the station
            Station = nsd.Station;
            // Add station to selector
            this.StationComboBox.Items.Add(nsd.Station);
            // Get new record.
            AddRecord();
        }
        /// <summary>
        /// EDIT pressed, edit a record
        /// </summary>
        private void EditToolStripButton_Click(object sender, EventArgs e)
        {
            if (this.fishBindingSource.Count == 0) return;
            if (EditCatch(CurrentRow, false) != System.Windows.Forms.DialogResult.Cancel)
                this.LocalData.Save();
        }
        /// <summary>
        /// Edit/add a record
        /// </summary>
        /// <param name="aRow">Record to add/edit</param>
        /// <param name="aAddNew">Add it true, else edit</param>
        /// <returns>Result of the dialog, Cancel=cancel, OK = Save, Retry=Save and add another</returns>
        private DialogResult EditCatch(LocalDataSet.FishRow aRow, bool aAddNew)
        {
            CatchDialog cd = new CatchDialog(aRow);
            return cd.ShowDialog(aAddNew);
        }
        /// <summary>
        /// ADD pressed, add a new record
        /// </summary>
        private void AddToolStripButton_Click(object sender, EventArgs e)
        {
            AddRecord();
        }
        /// <summary>
        /// Shorthand to get record at row of datagrid
        /// </summary>
        /// <param name="aRowIndex">DataGridView row index</param>
        /// <returns>Record at that row</returns>
        private LocalDataSet.FishRow RowAt(int aRowIndex)
        {
            return (LocalDataSet.FishRow)((DataRowView)this.fishDataGridView.Rows[aRowIndex].DataBoundItem).Row;
        }
        /// <summary>
        /// Shorthand for current DataGridView record
        /// </summary>
        private LocalDataSet.FishRow CurrentRow
        {
            get { return (LocalDataSet.FishRow)((DataRowView)this.fishBindingSource.Current).Row; }
        }
        /// <summary>
        /// Add a new row
        /// </summary>
        private void AddRecord()
        {
            DialogResult Result = System.Windows.Forms.DialogResult.Retry;
            while (Result == System.Windows.Forms.DialogResult.Retry) // Using Retry as 'keep going'
            {
                LocalDataSet.FishRow NewRow = this.LocalData.Fish.NewFishRow();
                // Try to get the last row
                if (Properties.Settings.Default.AllowDefaults && this.fishBindingSource.Count > 0)
                {
                    // Copy the defaults
                    int hid = NewRow.HookID;
                    LocalDataSet.FishRow LastRow = CurrentRow;
                    NewRow.ItemArray = LastRow.ItemArray;
                    NewRow.HookID = hid;
                }
                // Make sure the index is OK
                NewRow.VesselCode = this.VesselCode;
                NewRow.Cruise = this.Cruise;
                NewRow.Station = Station;
                // Edit it
                Result = EditCatch(NewRow, true);
                if (Result != System.Windows.Forms.DialogResult.Cancel) // Retry and OK are good-to-go
                {
                    // Add to the table and save it
                    this.LocalData.Fish.AddFishRow(NewRow);
                    this.LocalData.Save();
                    // Put in the table
                    Setup();
                }
            }
        }
        /// <summary>
        /// Pressed DELETE
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DeleteToolStripButton_Click(object sender, EventArgs e)
        {
            if (this.fishBindingSource.Count == 0) return;
            if (MessageBox.Show("Delete selected item?", "DELETE", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No) return;
            CurrentRow.Delete();
            this.fishDataGridView.Refresh();
            this.LocalData.Save();
        }
        /// <summary>
        /// Selected new station
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StationComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            Station = (string)this.StationComboBox.SelectedItem;
            Setup();
        }
        /// <summary>
        /// Make the grid cells look nice
        /// </summary>
        private void FishDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (e.RowIndex < 0 || e.Value == Convert.DBNull) return;
            string Property = ((DataGridView)sender).Columns[e.ColumnIndex].DataPropertyName;
            if (Property == "SexCode")
            {
                e.Value = RowAt(e.RowIndex).SexName;
                e.FormattingApplied = true;
            }
            else if (Property == "StageCode")
            {
                e.Value = RowAt(e.RowIndex).StageName;
                e.FormattingApplied = true;
            }
            else if (Property == "MortalityCode")
            {
                e.Value = RowAt(e.RowIndex).MortalityName;
                e.FormattingApplied = true;
            }
            else if (Property == "Weight")
            {
                this.fishDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.ForeColor =
                this.fishDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.SelectionForeColor =
                    e.CellStyle.ForeColor =
                    e.CellStyle.SelectionForeColor =
                        RowAt(e.RowIndex).WeightEstimated ? Color.Blue : this.fishDataGridView.ForeColor;
                if ((double)e.Value == 0d)
                {
                    e.Value = string.Empty;
                    e.FormattingApplied = true;
                }
            }
            else if (Property.StartsWith("Len"))
            {
                this.fishDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.ForeColor =
                this.fishDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.SelectionForeColor =
                    e.CellStyle.ForeColor =
                    e.CellStyle.SelectionForeColor =
                        RowAt(e.RowIndex).LengthEstimated ? Color.Blue : this.fishDataGridView.ForeColor;
            }
            if (e.Value is double && e.Value != null && (double)e.Value == 0d)
            {
                e.Value = string.Empty;
                e.FormattingApplied = true;
            }
        }
        /// <summary>
        /// Setup selected, show the settings menu
        /// </summary>
        private void SetupToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Set the cruise drop-down from the database
            SettingsDialog vcd = new SettingsDialog(
                this.LocalData.Fish.Select(Q => Q.Cruise).Distinct().ToArray());
            if (vcd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                Setup();
        }
        /// <summary>
        /// Exit selected
        /// </summary>
        private void ExitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.LocalData.Save();
            Close();
        }
        /// <summary>
        /// Utilities selected, show the utilities form
        /// </summary>
        private void UtilitiesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UtilityDialog ud = new UtilityDialog();
            DialogResult Result = ud.ShowDialog();
            if (Result == System.Windows.Forms.DialogResult.Cancel) return;
            if (Result == System.Windows.Forms.DialogResult.Retry)
            {
                this.DialogResult = System.Windows.Forms.DialogResult.Retry;
                Close();
                return;
            }
            DataSets.Glob.Support.Load();
            // CatchDialog.ReloadTax(this.LocalData.Fish);
        }
        /// <summary>
        /// Print selected, print the report
        /// </summary>
        private void PrintToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.commentDataGridViewTextBoxColumn.Visible = false;
            string Saved = this.fishBindingSource.Filter;
            // Show all stations
            this.fishBindingSource.Filter = "VesselCode = '" + this.VesselCode + "' AND Cruise = '" + Cruise + "'"; 
            new PrintForm(this.fishDataGridView).ShowDialog();
            this.fishBindingSource.Filter = Saved;
            this.commentDataGridViewTextBoxColumn.Visible = true;
        }
        /// <summary>
        /// Post selected, show post screen
        /// </summary>
        private void PostToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DataSets.PostFishDialog cpf = new DataSets.PostFishDialog(this.VesselCode, this.Cruise);
            // cpf.HelpMe = ShowHelp;
            cpf.VesselName = Properties.Settings.Default.VesselName;
            cpf.ShowDialog();
        }
        /// <summary>
        /// Toolstrip double-clicked, size the form to sane size
        /// </summary>
        private void MainToolStrip_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
            this.Size = this.MinimumSize;
        }
        /// <summary>
        /// Pressed Help, show help screen
        /// </summary>
        private void helpToolStripButton_Click(object sender, EventArgs e)
        {
            ShowHelp((((ToolStripMenuItem)sender).Text == "Catch Entry") ? "CatchEntry.htm" : "CatchProcessing.htm");
        }
        /// <summary>
        /// The help screen is a browser window
        /// </summary>
        private Helper HelpScreen = null;
        /// <summary>
        /// Show the help screen
        /// </summary>
        /// <param name="aDoc">HTML to show</param>
        public void ShowHelp(string aDoc)
        {
            if (this.HelpScreen == null || this.HelpScreen.IsDisposed) 
                this.HelpScreen = 
                    new Helper(System.IO.Path.Combine(Application.StartupPath, "Docs", aDoc));
            this.HelpScreen.Show();
            this.HelpScreen.WindowState = FormWindowState.Normal;
            this.HelpScreen.BringToFront();
        }
        /// <summary>
        /// Double-clicked cell - shortcut for EDIT
        /// </summary>
        private void fishDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            EditToolStripButton_Click(sender, new EventArgs());
        }
        /// <summary>
        /// About selected, show About
        /// </summary>
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new AboutBox().ShowDialog();
        }
        /// <summary>
        /// Summary selected, show the Summary screen
        /// </summary>
        private void summaryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new SummaryTreeForm().ShowDialog();
        }
        /// <summary>
        /// User types into the Station selector, look for [ENTER]
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StationComboBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13) //.KeyCode == Keys.Enter)
            {
                e.Handled = true;
                StationChanges();
            }
        }
        /// <summary>
        /// User focus left the station selector
        /// </summary>
        private void StationComboBox_Leave(object sender, EventArgs e)
        {
            StationChanges();
        }
        /// <summary>
        /// Either [ENTER] was pressed inside the station selector or focus left, Set the station
        /// </summary>
        private void StationChanges()
        {
            int StationNu = -1;
            int ix;
            if (string.IsNullOrEmpty(this.StationComboBox.Text) || 
                !int.TryParse(this.StationComboBox.Text, out StationNu) || StationNu < 0 ||
                (ix = this.StationComboBox.FindStringExact(StationNu.ToString("000"))) < 0)
                this.StationComboBox.Text = Station;
            else
                this.StationComboBox.SelectedIndex = ix;
        }
        /// <summary>
        /// User selected Save As XML, copy the database to where selected.
        /// </summary>
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.SaveAsFileDialog.DefaultExt = "XML";
            this.SaveAsFileDialog.FileName = "Catch.XML";
            this.SaveAsFileDialog.Filter = "XML file|*.xml";
            this.SaveAsFileDialog.Title = "Save CatchProcessing XML database";
            if (this.SaveAsFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    System.IO.File.Copy(DataSets.LocalDataSet.DefaultXMLFile, this.SaveAsFileDialog.FileName);
                }
                catch (Exception Ex)
                {
                    MessageBox.Show("Error saving as " + this.SaveAsFileDialog.FileName+" : "+Ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        /// <summary>
        /// User selected Save As CSV, convert and save
        /// </summary>
        private void cSVToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.SaveAsFileDialog.DefaultExt = "CSV";
            this.SaveAsFileDialog.FileName = "Catch.csv";
            this.SaveAsFileDialog.Filter = "CSV file|*.csv";
            this.SaveAsFileDialog.Title = "Save CatchProcessing CSV database";
            if (this.SaveAsFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    System.IO.File.WriteAllText(this.SaveAsFileDialog.FileName, this.LocalData.ToCSV());
                }
                catch (Exception Ex)
                {
                    MessageBox.Show("Error saving as " + this.SaveAsFileDialog.FileName + " : " + Ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void InfoToolStripButton_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(this.Station)) return;
            new StationInfoDialog(this.VesselCode, this.Cruise, this.Station).ShowDialog();

        }

        private void StationComboBox_DrawItem(object sender, DrawItemEventArgs e)
        {
            string lStation = (string)this.StationComboBox.Items[e.Index];
            e.DrawBackground();
            bool GotItems = this.LocalData.Fish.Where(qR => qR.Station == lStation).Any();
            Color fc = GotItems ? e.ForeColor : Color.Red;
            if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
                fc = GotItems ? Color.Blue : Color.Purple;
            using (Brush br = new SolidBrush(fc))
                e.Graphics.DrawString(lStation, e.Font, br, e.Bounds);
            e.DrawFocusRectangle();
        }
    }
}
